#include"mystdio.h"

MY_FILE* getMY_FILE(int fd, int flag){
  MY_FILE* newfile = (MY_FILE*)malloc(sizeof(MY_FILE));
  if(!newfile){
    perror("malloc");
    return NULL;
  }
  newfile->_buffer_len = 0;
  newfile->_fileno = fd;
  newfile->_flush_strategy = LINE_FLUSH;
  newfile->_flags = flag;
  memset(newfile->_stat_buffer, 0, BUFFER_SIZE);

  return newfile;
}

MY_FILE* MYfopen(const char * filename, const char * mode){
  int fd = -1;
  int flag = 0;
  if(strcmp(mode, "w") == 0){
    flag = O_CREAT | O_WRONLY | O_TRUNC;
    fd = open(filename, flag, 0666);
    if(fd < 0) return NULL;
  }
  else if(strcmp(mode, "r") == 0){
    flag = O_RDONLY;
    fd = open(filename,flag);
    if(fd < 0) return NULL;
  }
  else if(strcmp(mode, "a") == 0){
    flag = O_CREAT | O_WRONLY | O_APPEND;
    fd = open(filename, flag, 0666);
    if(fd < 0) return NULL;
  }
  //else if... 其他打开方式 这里就不写了
  else{
    //没有该种打开方式
    const char* msg = "No such a mode\n";
    write(1, msg, strlen(msg));
    return NULL;
  }

  MY_FILE* mpf = getMY_FILE(fd, flag);
  return mpf;
}


int MYfclose(MY_FILE* stream){
  int cd = close(stream->_fileno);
  //进程退出需要强制刷新当前MY_FILE中的缓冲区
  MYfflush(stream); 
  //
  
  //释放文件
  free(stream);

  return cd == 0; 
}

size_t MYfwrite (const void * ptr, size_t size, size_t count, MY_FILE* stream ){
  //ptr里面是要写入文件的数据
  
  char* src = (char*)ptr;//写入字符的来源 -> 一个字符一个字符写入缓冲区
  int offset = 0;//src写入的起始位置(可能写入的字符数 > 缓冲区空间，需要多次写入)
  size_t src_len = strlen(src);


  int buffer_len = stream->_buffer_len;//当前缓冲区内字符个数
  int left_space = BUFFER_SIZE - buffer_len;//当前缓冲区剩余空间
  int WR_ByteNum = (size * count) >= src_len ? src_len : size * count;
    //本次fwrite函数 剩余要写入的字节


  while(WR_ByteNum > 0){
    //单次写入的字符数
    int cur_write_ByteNum = (WR_ByteNum >= left_space) ? left_space : WR_ByteNum;
    
    if(stream->_flush_strategy == LINE_FLUSH){
     //行刷新 此时的缓冲区内一定是没有换行符的
      if(left_space == 0){
        MYfflush(stream);
        buffer_len = 0;
        left_space = BUFFER_SIZE; 
        WR_ByteNum -= cur_write_ByteNum;
      }

      while(offset < cur_write_ByteNum){
        char c = src[offset++]; 
        stream->_stat_buffer[buffer_len++] = c;
        if(c == '\n'){
          MYfflush(stream);
          buffer_len = 0;
        } 
        else{
         //还需要判断一下是否处于满状况
          if(buffer_len == BUFFER_SIZE){
            MYfflush(stream);
            buffer_len = 0;
          }
        }

      }
      WR_ByteNum -= cur_write_ByteNum;
    }

    else{
      //剩下的就是无缓存(写入立马刷新)
      //全缓存 写满才刷新
      
      strncpy(stream->_stat_buffer + buffer_len, src + offset, cur_write_ByteNum);
      if(stream->_flush_strategy == NONE_FLUSH){
        //强制刷新缓冲区
        MYfflush(stream);
        buffer_len = 0;
        left_space = BUFFER_SIZE; 
        WR_ByteNum -= cur_write_ByteNum;
        offset += cur_write_ByteNum;
      }

      else{
        //全缓存
        if(buffer_len + cur_write_ByteNum == BUFFER_SIZE){
          //满了
          MYfflush(stream);
          buffer_len = 0;
          WR_ByteNum -= cur_write_ByteNum;
          offset += cur_write_ByteNum;
        }
      }
    
    }
  }

  return 1;
}   

int MYfflush(MY_FILE* stream){
  int wd = write(stream->_fileno, stream->_stat_buffer, strlen(stream->_stat_buffer));
  stream->_buffer_len = 0;
  memset(stream->_stat_buffer, 0, BUFFER_SIZE);
  fsync(stream->_fileno);
  if(wd >= 0) return 1;
  else return 0;
}
